package com.lebang.aop;

import com.lebang.common.AllMemberLock;
import com.lebang.component.RedisSdkClient;
import com.lebang.model.AllLockModel;
import com.lebang.service.buss.MemberService;
import com.lebangweb.response.Callback;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

@Aspect
@Component
public class AllMemberLockAop {
    private ThreadLocal<AllLockModel> thread = new ThreadLocal<>();


    @Autowired
    private RedisSdkClient redisSdkClient;
    @Autowired
    private MemberService memberService;

    public static String ALL_MEMBER_LOCK = "ALL_Member_LOCK:";

    @Pointcut("@annotation(com.lebang.common.AllMemberLock)")
    public void pointCut() {
    }

    @Around("pointCut()")
    public Object aroundMethod(ProceedingJoinPoint point) throws Throwable {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String phone = memberService.getPhoneById(request.getHeader("userid"));
        thread.set(new AllLockModel(phone));
        MethodSignature methodSignature = (MethodSignature) point.getSignature();
        Method method = methodSignature.getMethod();
        AllMemberLock userLoginToken = method.getAnnotation(AllMemberLock.class);
        try {
            boolean lock = redisSdkClient.tryGetDistributedLock(ALL_MEMBER_LOCK + thread.get().getPhone(), thread.get().getUuid(), userLoginToken.ttl());
            if (!lock) {
                return Callback.fail("406", "操作频繁!", null);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return Callback.fail("406", "操作频繁!", null);
        }
        return point.proceed();
    }

    @After("pointCut()")
    public void afterMethod(JoinPoint point) {
        MethodSignature methodSignature = (MethodSignature) point.getSignature();
        Method method = methodSignature.getMethod();
        AllMemberLock userLoginToken = method.getAnnotation(AllMemberLock.class);
        if (userLoginToken.automaticRelease()) {
            redisSdkClient.releaseDistributedLock(ALL_MEMBER_LOCK + thread.get().getPhone(), thread.get().getUuid());
        }
        thread.remove();
    }


}
